#
# PVCSConfigFileWriter.py
#
# this class writes the content of a PVCS config files
#
# Author: Uwe Stieber
# Copyright (c) 1998, 1999 TakeFive Software, Salzburg
#

# import some system modules
import string
import os
import sys
import re

# import PVCS constants and helper functions
import PVCSConstants

# some SNiFF+ modules
from etgui import *
import vcs

class PVCSConfigFileWriter:
	# some class privates
	__fileObject = None		 # store the file object of the
								# config file
	__tempFileObject = None  # file object for temporary file
	__theConfigFileName = "" # name of the config file
	__tempFileName = ""		 # name of the temporary file

	def __init__(self, aFileName):
		# constructor
		if PVCSConstants.TEST:
			print "(PVCS Config File Writer)@B@g>>>@x __init__@B"
			print "(PVCS Config File Writer)\tconfig file name: @B@b%s@x@B" % aFileName
		self.__theConfigFileName = aFileName
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x __init__@B"
		return

	def openConfigFile(self):
		# open the file for reading
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x openConfigFile@B"
		if self.__fileObject == None:
			self.__fileObject = open(self.__theConfigFileName, "r")
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x openConfigFile@B"
		return

	def closeConfigFile(self):
		# close the config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x closeConfigFile@B"
		if self.__fileObject != None:
			self.__fileObject.close()
			self.__fileObject = None
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x closeConfigFile@B"
		return

	def customUpdateSuffixRules(self, tempFileObject, params):
		# write really the new suffix rules to the config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x customUpdateSuffixRules@B"
		# write the 'ARCHIVESUFFIX' rule lines
		for aExtension in params.keys():
			tempFileObject.write("ARCHIVESUFFIX %s = %s\n" % (aExtension, params[aExtension]))
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x customUpdateSuffixRules@B"
		return

	def updateSuffixRules(self, suffixRuleDict):
		# write new suffix rules to config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x updateSuffixRules@B"
		self.updateConfigFile("ArchiveSuffix",
								"",
								self.customUpdateSuffixRules,
								suffixRuleDict
								)
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateSuffixRules@B"
		return

	def customIncludeConfigFiles(self, tempFileObject, params):
		# writes the real include lines to the config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x customIncludeConfigFiles@B"
		if len(params) > 0:
			tempFileObject.write("\n")
			for aIncludedConfigFile in params:
				if aIncludedConfigFile != "":
					tempFileObject.write("Include %s\n" % aIncludedConfigFile)
				tempFileObject.write("\n")
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x customIncludeConfigFiles@B"
		return

	def includeConfigFiles(self, pvcsMasterConfig, pvcsProjectConfig):
		# write include files to config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x includeConfigFile@B"
		self.updateConfigFile("",
								"Include",
								self.customIncludeConfigFiles,
								[pvcsMasterConfig, pvcsProjectConfig]
								)
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x includeConfigFile@B"
		return

	def customUpdateDiagnosticFlag(self, tempFileObject, params):
		# writes the real diagnostic tag to the config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x customUpdateDiagnosticFlag@B"
		if len(params) > 0:
			tempFileObject.write("DIAGNOSTIC = %d\n" % params[0])
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x customUpdateDiagnosticFlag@B"
		return

	def updateDiagnosticFlag(self, diagnosticFlag):
		# write diagnostic level to config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x updateDiagnosticFlag@B"
		self.updateConfigFile("Diagnostic",
								"",
								self.customUpdateDiagnosticFlag,
								[diagnosticFlag]
								)
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateDiagnosticFlag@B"
		return

	def customUpdateSignOnFlag(self, tempFileObject, params):
		# writes the real SignOn tag to the config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x customUpdateSignOnFlag@B"
		if len(params) > 0:
			if params[0] == 0:
				tempFileObject.write("NOSIGNON\n")
			else:
				tempFileObject.write("SIGNON\n")
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x customUpdateSignOnFlag@B"
		return

	def updateSignOnFlag(self, signonFlag):
		# write SignOn flag to config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x updateSignOnFlag@B"
		self.updateConfigFile("SignOn|NoSignOn",
								"",
								self.customUpdateSignOnFlag,
								[signonFlag]
								)
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateSignOnFlag@B"
		return

	def customUpdateQuietFlag(self, tempFileObject, params):
		# writes the real Quiet tag to the config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x customUpdateQuietFlag@B"
		if len(params) > 0:
			if params[0] == 0:
				tempFileObject.write("VERBOSE\n")
			else:
				tempFileObject.write("QUIET\n")
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x customUpdateQuietFlag@B"
		return

	def updateQuietFlag(self, quietFlag):
		# write Quiet flag to config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x updateQuietFlag@B"
		self.updateConfigFile("Quiet|Verbose",
								"",
								self.customUpdateQuietFlag,
								[quietFlag]
								)
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateQuietFlag@B"
		return

	def updateConfigFile(self, includeTagString="", excludeTagString="", customFunction, customParams):
		# write a changed tag to config file
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x updateConfigFile@B"
		if vcs.is_writable(self.__theConfigFileName):
			try:
				# open the config file
				self.openConfigFile()
			except IOError:
				# stop processing
				if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateConfigFile (IOError Exception)@B"
				return
			# check, if we can create a temporary file
			if vcs.is_writable(PVCSConstants.getTempDir()):
				# ok, we can create a temporary file
				self.__tempFileName = PVCSConstants.getTempFile()
				try:
					# open the temp file
					self.__tempFileObject = open(self.__tempFileName, "w")
				except IOError:
					# stop processing
					ShowAlert(eAlertNote, "Temp file @B%s@B cannot be opened ! Cannot finish updateing of config files !" % self.__tempFileName)
					if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateDiagnosticFlag (IOError Exception)@B"
					raise PVCSConstants.PVCSErrorWritingConfigFile
					return
				# copy now all lines up to the give tag and exclude the given tag
				self.copyLinesUntil(includeTagString, excludeTagString)
				# write the new rule lines
				if customFunction != None:
					customFunction(self.__tempFileObject, customParams)
				# copy the rest of the lines
				self.copyLinesExcluding(includeTagString, excludeTagString)
				# close temp file
				if self.__tempFileObject != None:
					self.__tempFileObject.close()
					self.__tempFileObject = None
			else:
				# temp dir is not writeable
				ShowAlert(eAlertNote, "Temp directory @B%s@B is not writeable ! Cannot finish updateing of config files !" % PVCSConstants.getTempDir())
				# close the file before throwing the exception
				self.closeConfigFile()
				raise PVCSConstants.PVCSErrorWritingConfigFile
			# close the file finally
			self.closeConfigFile()
			# overwrite old config file
			try:
				if sys.platform == "win32":
					vcs.chmod(self.__theConfigFileName, 'ug+w')
				os.remove(self.__theConfigFileName)
				if sys.platform == "win32":
					try:
						os.rename(self.__tempFileName, self.__theConfigFileName)
					except:
						# renaming failed
						ShowAlert(eAlertNote, "Renaming from @B%s@B to @B%s@B failed ! Perform renaming manually before continue using the integration !" % (self.__tempFileName, self.__theConfigFileName))
				else:
					try:
						self.__fileObject = open(self.__theConfigFileName, "w")
						self.__tempFileObject = open(self.__tempFileName, "r")
						self.__fileObject.writelines(self.__tempFileObject.readlines())
						self.__tempFileObject.close()
						self.__fileObject.close()
						self.__fileObject = None
						self.__tempFileObject = None
						os.remove(self.__tempFileName)
					except os.error, exc:
						if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateConfigFile (os.error: %s)@B" % exc
						return
					except:
						if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateConfigFile (IOError)@B"
						return
			except os.error, exc:
				ShowAlert(eAlertNote, "Removing of old config file @B%s@B failed ! Exception is 'os.error' and exception argument is '%s' ! Cannot finish updateing of config files !" % (self.__theConfigFileName, exc))
				if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateConfigFile (os.error: %s)@B" % exc
				return
			except:
				ShowAlert(eAlertNote, "Removing of old config file @B%@B failed ! Exception unknown ! Cannot finish updateing of config files !" % self.__theConfigFileName)
				if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateConfigFile (IOError)@B"
				return
		else:
			# config file is not writeable
			ShowAlert(eAlertNote, "Config file @B%s@B is not writeable ! Cannot finish updateing of config files !" % self.__theConfigFileName)
			raise PVCSConstants.PVCSErrorWritingConfigFile
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x updateConfigFile@B"
		return

	def copyLinesUntil(self, aMatchPattern, aExcludePattern = "", regexFlags = re.I):
		# copy all lines until the line contains the text 'aLineStart'
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x copyLinesUntil '%s', '%s'@B" % (aMatchPattern, aExcludePattern)
		if self.__fileObject != None and self.__tempFileObject != None:
			# read the lines
			lastLine = "None"
			aLine = self.__fileObject.readline()
			while aLine != "":
				if PVCSConstants.TEST:
					print "(PVCS Config File Writer)\t@Bcurrent Line: '@b%s@x'@B" % aLine
				# check the stop condition
				if aMatchPattern != "":
					if re.match(aMatchPattern, aLine, regexFlags) != None:
						# stop processing
						if PVCSConstants.TEST:
							print "(PVCS Config File Writer)\t@Bstop condition found !@B"
						break
				else:
					# stop at first empty line
					if string.lstrip(aLine) == "":
						# stop processing
						if PVCSConstants.TEST:
							print "(PVCS Config File Writer)\t@Bstop condition found !@B"
						break
				if string.lstrip(aLine) != string.lstrip(lastLine):
					# write line to temp file
					if aExcludePattern != "":
						# have to check, if we should exclude the line
						if re.match(aExcludePattern, aLine, regexFlags) == None:
							# no exclude
							self.__tempFileObject.write(aLine)
							lastLine = aLine
						else:
							if PVCSConstants.TEST:
								print "(PVCS Config File Writer)\t@Bexclude condition found !@B"
					else:
						self.__tempFileObject.write(aLine)
						lastLine = aLine
				# read next line
				aLine = self.__fileObject.readline()
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x copyLinesUntil@B"
		return

	def copyLinesExcluding(self, aMatchPattern, aExcludePattern = "", regexFlags = re.I):
		# copy all lines excluding the line that matches 'aMatchPattern'
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@g>>>@x copyLinesExcluding '%s'; '%s'@B" % (aMatchPattern, aExcludePattern)
		if self.__fileObject != None and self.__tempFileObject != None:
			# read the lines
			lastLine = "None"
			aLine = self.__fileObject.readline()
			while aLine != "":
				if PVCSConstants.TEST:
					print "(PVCS Config File Writer)\t@Bcurrent Line: '@b%s@x'@B" % aLine
				# check the copy condition
				if aMatchPattern != "":
					if re.match(aMatchPattern, aLine, regexFlags) == None:
						# write line to temp file
						if string.lstrip(aLine) != string.lstrip(lastLine):
							if aExcludePattern != "":
								# we have to exclude something
								if re.match(aExcludePattern, aLine, regexFlags) == None:
									# no exclude
									self.__tempFileObject.write(aLine)
									lastLine = aLine
								else:
									if PVCSConstants.TEST:
										print "(PVCS Config File Writer)\t@Bexclude condition found !@B"
							else:
								self.__tempFileObject.write(aLine)
								lastLine = aLine
					else:
						if PVCSConstants.TEST:
							print "(PVCS Config File Writer)\t@Bexclude condition found !@B"
				else:
					# copy all rest lines
					if string.lstrip(aLine) != string.lstrip(lastLine):
						if aExcludePattern != "":
							# we have to exclude something
							if re.match(aExcludePattern, aLine, regexFlags) == None:
								# no exclude
								self.__tempFileObject.write(aLine)
								lastLine = aLine
							else:
								if PVCSConstants.TEST:
									print "(PVCS Config File Writer)\t@Bexclude condition found !@B"
						else:
							self.__tempFileObject.write(aLine)
							lastLine = aLine
				# read next line
				aLine = self.__fileObject.readline()
		if PVCSConstants.TEST: print "(PVCS Config File Writer)@B@r<<<@x copyLinesExcluding@B"
		return
